import csv
import os
import time

from django import forms
from django.conf import settings
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required, permission_required
from django.core.mail import send_mail
from django.core.paginator import Paginator
from django.db.models import Count
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.template import Template, Context
from django.views.decorators.cache import cache_page

from index.forms import UserModelForm
from index.models import Book, PubName, UserInfo


def test_html(request):
    a = {}  # 创建空字典，模板必须以字典的形式进行传参
    a['name'] = 'C语言中文网'
    a['course'] = ["Python", "C", "C++", "Java"]
    a['b'] = {'name': 'C语言中文网', 'address': 'http://c.biancheng.net/'}
    a['test_hello'] = test_hello
    a['class_obj'] = Website()
    return render(request, 'test_html.html', a)
    # return render(request, 'test.html', {'name': 'c语言中文网'})  # 根据字典数据生成动态模板


def test_hello():
    return '欢迎来到C语言中文网'


class Website:
    def Web_name(self):
        return 'Hello，C语言中文网!'


def test_if(request):
    dic = {'x': 2 ** 4}
    return render(request, 'test_if.html', dic)


def Hello_MyWeb(request, id):
    # 调用template()方法生成模板
    t = Template("""
                        {% if web.name == 'C语言中文网' %}
                              {% if printable %}
                                     <h1>Hello C语言中文网</h1>
                                     <p>{{ web.id }}</p>
                              {% else %}
                                      <h2>欢迎您下次访问，C语言中文网</h2>
                              {% endif %}
                        {% else %}
                              <h2>学习python的django</h2>
                        {% endif %}
                                      """)
    c = Context({'web': {'name': 'C语言中文网', "id": id}, 'printable': True})  # Context必须是字典类型的对象，用来给模板传递数据
    html = t.render(c)
    return HttpResponse(html)


def test_for(request):
    # 调用template()方法生成模板
    t1 = Template("""
                    {% for item in list %}
                        <li>{{ item }}</li>
                    {% empty %}
                        <h1>如果找不到你想要，可以来C语言中文网(网址：http://c.biancheng.net/)</h1>
                    {% endfor %}
                              """)
    # 调用 Context()方法
    c1 = Context({'list': ['Python', 'Java', 'C', 'Javascript', 'C++']})
    html = t1.render(c1)
    return HttpResponse(html)


def test01_for(request):
    # 使用嵌套for标签依次遍历列表取值
    website = Template("""
     {% for course in list01 %}
     <div>
        {% for coursename in course %}
        <p><b>{{ coursename }}</b></p>
        {% endfor %}
     </div>
     {% endfor %}
     """)
    webname = Context({'list01': [['Django', 'Flask', 'Tornado'], ['c语言中网', 'Django官网', 'Pytho官网']]})
    html = website.render(webname)
    return HttpResponse(html)


def test_forloop(request):
    a = Template("""
     {% for item in lists %}
     <div>
        <p><b>{{ forloop.revcounter }}:{{ item }}</b></p>
     </div>
     {% endfor %}
     """)
    b = Context({'lists': ['c语言中网', 'Django官网', 'Pytho官网']})
    html = a.render(b)
    return HttpResponse(html)  # 数字与元素以 1:'c语言中文网' 的形式出现


def test_url(request):
    return render(request, 'test_url.html')


def test_tag(request):
    return render(request, 'test_tags.html')


def test_inclusion(request):
    return render(request, 'inclusion.html', {'varible': 'Hello'})


def index_html():
    pass


def redict_url(request):
    return render(request, 'index/newtest.html')


def test_to_reverse(request):
    from django.urls import reverse
    return HttpResponseRedirect(reverse('index:detail_hello', current_app=request.resolver_match.banespace))


def year_test(request, year):
    year = int(year)  # 转换整形
    return render(request, year)


def num1_view(request, id):
    pass


def num2_view(request, id):
    pass


def num3_view(request, id):
    pass


def BookName(request):
    books = Book.objects.raw("select * from index_book")  # 书写sql语句
    return render(request, "index/allbook.html", locals())


def test_annotate(request):
    # 得到所有出版社的查询集合QuerySet
    bk_set = Book.objects.values('price')
    # bk=Book.objects.get(id=1)
    # print('书名:',bk.title,'出版社是:',bk.pub.pubname)
    # 根据出版社QuerySet查询分组，出版社和Count的分组聚合查询集合
    bk_count_set = bk_set.annotate(myCount=Count('price'))  # 返回查询集合
    for item in bk_count_set:  # 通过外键关联进行查询bk_set.pub.pubname
        print("价格是:", item['price'], "同等价格书籍数量：", item['myCount'])
    return HttpResponse('请在CMD命令行控制台查看结果')


# 使用FBV方式
def login_fbv(request):
    if request.method == "GET":
        return HttpResponse("登录成功")
    elif request.method == "POST":
        return HttpResponse("这是POST请求")


from django.views import View


# 使用CBV方式
class LoginView(View):
    username = 'xiaoli'

    def get(self, request):
        return HttpResponse("登录成功%s" % self.username)

    def post(self, request):
        return HttpResponse("POST请求")


class LoginViewChild(LoginView):
    username = "xiaowang"


class LoginForm(forms.Form):  # 继承自Form类，
    user_name = forms.CharField(label="用户名", min_length=6, max_length=12)  # 新建表单字段
    user_password = forms.CharField(label="用户密码", min_length=8)


# 第二步围绕form对象完成表单。
def logins(request):  # 定义登录处理函数login()
    if request.method == "POST":  # request是 HttpRequest的对象，利用它的的method属性，判断请求方法。
        form = LoginForm(request.POST)  # 实例化对象，post提交数据是QuerySet类型的字典，GET方法与其一样。
        if form.is_valid():  # 提供验证判断是否有效，成立则返回是Ture
            return HttpResponse("登录成功")
    else:
        form = LoginForm()
    return render(request, "index/login.html", locals())


def set_cookie_view(request):
    resp = HttpResponse()
    resp.set_cookie("username", "cbiancheng", 3600)
    return resp


def get_cookie_view(request):
    value = request.COOKIES.get("username")
    return HttpResponse('--MY COOKIE is--%s' % value)


# 用来显示查询页面
def search_ttile_form(request):
    return render(request, 'index/search_title.html', context={'form': TitleSearch()})  # 实例化表单对象


class TitleSearch(forms.Form):
    title = forms.CharField(label="书名", label_suffix="", error_messages={'required': '请输入正确的title'})


def search_title(request):
    form = TitleSearch(request.GET)
    if form.is_valid():  # 第一步验证成功
        books = Book.objects.filter(title__icontains=form.cleaned_data["title"])  # 调用cleaned_data属性获取清理后的数据
        if not books:
            return HttpResponseRedirect("/index/book_not_list")
        return render(request, 'index/book_list.html', locals())  # 查看返回结果
    else:
        # 将带有错误信息的表单实例作为上下文传递到需要渲染的模板中
        return render(request, 'index/search_title.html', {'form': form})


def book_not_list(request):
    return render(request, "index/book_not_list.html")


# 用来显示查询结果
def serch_title(request):
    # 查询title忽略大小写,所得类型为QuerySet
    title = Book.objects.filter(title__icontains=request.GET['title'])
    if not request.GET.get("title", ""):
        errors = ["输入的书名是无效的"]
        return render(request, "index/search_title.html", locals())
    return render(request, 'index/book_list.html', locals())


def book_table(request):
    try:
        all_book = Book.objects.all().order_by("-price")
        if not all_book:
            return HttpResponse('书籍信息表为空，请录入！')
    except Exception as e:
        print(e)
    return render(request, "index/book_table.html", locals())


@permission_required("index.can_view_book")
def add_book(request):
    if request.method == 'GET':
        return render(request, 'index/add_book.html')
    elif request.method == 'POST':
        # 添加书籍
        title = request.POST.get('title')
        if not title:
            return HttpResponse('请给出一个正确的title')
        pub = request.POST.get('pub')
        print(pub)
        price = float(request.POST.get('price', '999.99'))
        if not price:
            return HttpResponse('请输入价格')
        try:
            retail_price = float(request.POST.get('retail_price'))
            if not retail_price:
                return HttpResponse('请输入市场价')
        except Exception as e:
            print(e)
        # 判断title是不是已经存在了
        old_book = Book.objects.filter(title=title)
        if old_book:
            return HttpResponse('你输入的书籍系统已经存在 !')
        try:
            pub1 = PubName.objects.get(pubname=str(pub))
            Book.objects.create(title=title, price=price, retail_price=retail_price, pub=pub1)
        except Exception as e:
            print('Add ErrorReason is %s' % (e))
        return HttpResponseRedirect('/index/all_book')
    return HttpResponse('请使用正确Http请求方法 !')


def update_book(request, book_id):
    # 用 book_id给每个书籍加上标记
    # 将其作为查找书籍的参数
    book_id = int(book_id)
    try:
        book = Book.objects.get(id=book_id)
    except Exception as e:
        return HttpResponse('--没有找到任何书籍---')
    if request.method == 'GET':
        return render(request, 'index/update_book.html', locals())
    elif request.method == 'POST':
        print("这是post方法")
        price = request.POST.get('price')
        retail_price = request.POST.get('retail_price')
        if not price or not retail_price:
            return HttpResponse('请输入更改后的零售价或市场价！')
        price = float(price)
        retail_price = float(retail_price)
        # 修改对象属性值
        book.price = price
        book.retail_price = retail_price
        # 存储更新后的状态
        book.save()
        # 重定向至127.0.0.1:8000/index/all_book/
        return HttpResponseRedirect('/index/all_book')
    return HttpResponse("书籍信息更新功能")


def delete_book(request, book_id):
    book_id = int(book_id)
    try:
        book = Book.objects.get(id=book_id)
    except Exception as e:
        print('get查询出现了异常没找到数据', e)
        return HttpResponse('这里没有任何书籍可以被删除')
    if request.method == "GET":
        return render(request, 'index/delete_book.html', locals())
    elif request.method == "POST":
        book.delete()
        return HttpResponseRedirect("/index/all_book")
    return HttpResponse("书籍条目信息删除功能")


def user_add_form(request):
    if request.method == "Post":
        user = UserModelForm(request.Post)
        if user.is_valid():
            user = UserInfo.objects.create(username=user.cleaned_data['username'],
                                           password=user.cleaned_data["password"],
                                           gender=user.cleaned_data['gender'])
            # user_add.html只需要接收变量{{ user }}即可
            return render(request, 'index/user_add.html', locals())
        else:
            return render(request, 'index/useradd_model_form.html', context={'form': user})
    else:
        return render(request, 'index/useradd_model_form.html', {'form': UserModelForm()})


def page_test(request):
    # 测试分页功能
    books = Book.objects.all()
    paginator = Paginator(books, 2)
    num_p = request.GET.get("page", 1)  # page为键得到默认的页面1
    page = paginator.page(int(num_p))
    return render(request, "index/page_test.html", locals())


def send_email(request):
    subject = 'C语言中文网链接'  # 主题
    from_email = settings.EMAIL_HOST_USER  # 发件人，在settings.py中已经配置
    to_email = 'd_xianting@163.com'  # 邮件接收者列表
    # 发送的消息
    message = 'c语言中文网欢迎你点击登录 http://c.biancheng.net/'  # 发送普通的消息使用的时候message
    # meg_html = '<a href="http://www.baidu.com">点击跳转</a>'  # 发送的是一个html消息 需要指定
    send_mail(subject, message, from_email, [to_email])
    return HttpResponse('OK,邮件已经发送成功!')


def login_views(request):
    username = request.POST("username")
    password = request.POST("password")
    # 调用 authenticate对user进行认证
    user = authenticate(username=username, password=password)
    if user:
        # 调用auth的login api
        login(request, user)
        pass
    else:
        pass


@login_required
def search_title_views(request):
    return HttpResponse("登录成功后能看到！")


def uplod(request):
    if request.method == "GET":
        return render(request, "index/upload.html")
    elif request.method == "POST":
        file = request.FILES["myfile"]
        filename = os.path.join(settings.MEDIA_ROOT, file.name)
        with open(filename, "wb") as f:
            data = file.file.read()
            f.write(data)
            return HttpResponse("成功保存了%s 文件" % (file.name))


def list_uplod(request):
    file_list = []
    if request.method == "GET":
        return render(request, "index/list_uplod.html")
    elif request.method == "POST":
        files = request.FILES.getlist("myfiles")
        print(files)
        for file in files:
            print("file:", file)
            filename = os.path.join(settings.MEDIA_ROOT, file.name)
            with open(filename, "wb") as f:
                data = file.file.read()
                f.write(data)
            file_list.append(file.name)
        return HttpResponse("保存成功了{}文件".format([i for i in file_list]))


def test_csv(request):
    # 生成csv文本
    # 生成response的content-type头
    res = HttpResponse(content_type='text/csv')
    # 固定格式,添加 content-Disposition头，设置以附件方式下载，并给文件添加默认文件名
    res['Content-Disposition'] = 'attachment;filename="allUser.csv"'
    # 获取数据库中数据
    users = UserInfo.objects.all()
    # 生成writer的写对象
    writer = csv.writer(res)
    # 写csv表头，即想要展示字段名
    writer.writerow(['username', 'gender'])
    # 写具体数据
    for user in users:
        writer.writerow([user.username, user.gender])
    return res


# 在缓存有效时间内不会阻塞，直到缓存过期重新阻塞3秒
@cache_page(60)  # 缓存有效时间60s
def test_cache(request):
    t1 = time.time()  # 得到当前时间戳
    time.sleep(3)  # 阻塞三秒
    html = 't1 is %s' % (t1)
    return HttpResponse(html)


def test_time(request):
    if request.method == "GET":
        return render(request, "index/test_cache.html")
    elif request.method == "POST":
        t1 = time.time()
        time.sleep(3)
        return render(request, "index/test_cache.html", locals())


def request_started_callback(sender, **kwargs):
    print("请求开始：%s" % kwargs['environ'])


def request_finished_callback(sender, **kwargs):
    print("请求完成")
